<!-- 高德地图 -->
<template>
  <BasicModal v-bind="$attrs" @register="registerModal" :title="title" 
    @ok="handleSubmit" @cancel="handleDestroy" @closeFunc="handleDestroy" :width="width + 'px'">
  <a-input v-model:value="useAddress.address" placeholder="请选择地址"></a-input>
  <div class="demo-amap-app-container">
    <MySearchSelect placeholder="搜索地点" class="maps-search-select"
      @select="handleSelect" ref="searchSelectRef"
      :api="handleFetch" v-model:value="searchValue" resultField="data"
      :customOptions="true"
      :style="{ width: '450px' }" show-search allowClear>
      <template #customOptions="options">
        <template v-for="item in options" :key="`${item.value}`" >
          <SelectOption :value="item.value">
            <div class="addree-option">
              <span class="label">{{ item.label }}</span>
              <span class="detail">{{ item.detail }}</span>
            </div>
          </SelectOption>
        </template>
      </template>
    </MySearchSelect>

    <div style="background-color: #ffffff;">
      <div id="demo-amap-container" :style="'height: ' + height + 'px'"></div>
    </div>
  </div>
  <InfoWindow :selectAddress="selectAddress" @confirm="handleConfirmSelectAddress" ref="infoWindowRef"/>

</BasicModal>
</template>

<script lang="ts" setup>
import MySearchSelect from '/@/components/Form/src/my/components/MySearchSelect.vue';
import { SelectOption } from 'ant-design-vue';
import AMapLoader from '@amap/amap-jsapi-loader';
import InfoWindow from './InfoWindow.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { propTypes } from '/@/utils/propTypes';
import { BasicModal, useModalInner } from '/@/components/Modal';
import type { Location } from './data';
import { useGlobSetting } from '/@/hooks/setting';

/*在Vue3中使用时,需要引入Vue3中的shallowRef方法(使用shallowRef进行非深度监听,
因为在Vue3中所使用的Proxy拦截操作会改变JSAPI原生对象,所以此处需要区别Vue2使用方式对地图对象进行非深度监听,
否则会出现问题,建议JSAPI相关对象采用非响应式的普通对象来存储)*/
// import { shallowRef } from '@vue/reactivity';
import { ref, onUnmounted, unref, onMounted } from "vue";
import { cloneDeep } from 'lodash-es';

const { createMessage } = useMessage();
let map = null
let MyAMap : any = null
const infoWindowRef = ref()
const searchValue = ref('')
const searchSelectRef = ref()
const selectAddress = ref<any>({})
const useAddress = ref<any>({})
let mapPlugin : any = {}
const emit = defineEmits(['register', 'success']);
const props = defineProps({
  height: propTypes.number.def(550),
  width: propTypes.number.def(800),
  title: propTypes.string.def('修改地址'),
  /**
   * 地图key
   */
  mapKey: propTypes.string.def('66526c96e5fad2b84005d594162a455e')
});
const currentLocation = ref<Location>({})
interface Pois {
  // Location
  location: string[];
  pname: string;
  cityname: string;
  adname: string;
  address: string;
  name: string;
  id: string;
}
interface PoiList {
  pois: Pois[];
  count: number;
  pageIndex: number;
  pageSize: number;
}

interface PoiResult {
  poiList: PoiList
}

const autoCompleteResult = ref<any[]>([])
let autoOptions = {
  
};


const initMap = () => {
  const { domainUrl } = useGlobSetting()
  // @ts-ignore
  window._AMapSecurityConfig = {
    serviceHost: `${domainUrl}/_AMapService`,  
  }
  AMapLoader.load({
    // 申请好的Web端开发者Key，首次调用 load 时必填
    key: props.mapKey,
    // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
    version: "2.0",
    // plugins:[''], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
  }).then((AMap) => {
    console.log('init map');
    
    MyAMap = AMap
    map = new AMap.Map("demo-amap-container", {  //设置地图容器id
      resizeEnable: true,
      viewMode: "2D",    //是否为3D地图模式
      zoom: 14,           // 初始化地图级别
    });
    //使用CSS默认样式定义地图上的鼠标样式
    map.setDefaultCursor("pointer");

    updateMarker(currentLocation.value)

    // 添加插件
    AMap.plugin([
      "AMap.ToolBar", "AMap.Scale", "AMap.HawkEye", "AMap.Geolocation", "AMap.MouseTool",
      'AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Marker', 'AMap.Pixel', 'AMap.Geocoder'
    ], function () {
      // 异步同时加载多个插件
      // 添加地图插件
      // @ts-ignore
      map.addControl(new AMap.ToolBar()); // 工具条控件;范围选择控件
      // @ts-ignore
      map.addControl(new AMap.Scale()); // 显示当前地图中心的比例尺
      // @ts-ignore
      map.addControl(new AMap.HawkEye()); // 显示缩略图
      // @ts-ignore
      map.addControl(new AMap.Geolocation()); // 定位当前位置
    });

    // 单击
    // @ts-ignore
    map.on('click', (e) => {
      // lng ==> 经度值  lat => 维度值
      currentLocation.value = {
        lng: e.lnglat.getLng(),
        lat: e.lnglat.getLat()
      }
      selectAddress.value.address = ''
      updateMarker(currentLocation.value)
      handlerOpenInfoWindow(currentLocation.value)
    })
  }).catch(e => {
    console.log(e);
  })
}

//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
  console.log('init modal data', data);
  mapPlugin = {}
  infoWindowRef.value?.reset()
  searchSelectRef.value?.reset()
  setModalProps({ confirmLoading: false, draggable: false, canFullscreen: false });
  currentLocation.value = data.selectAddress.addressDetail?.location
  useAddress.value.address = data.selectAddress.address
  useAddress.value.location = currentLocation.value
  initMap()
});

onUnmounted(() => {
  // @ts-ignore
  map && map.destroy();
  console.log('地图已被销毁');
})

const handleConfirmSelectAddress = (address) => {
  console.log('select address', address);
  
  useAddress.value = address
}

const handleSelect = async (value) => {
  console.log('handleSelect: ', value);

  // 平移地图
  const poi = autoCompleteResult.value?.filter(e => e.id === value)
  if (poi && poi.length > 0) {
    const location = poi[0].location
    currentLocation.value = location
    selectAddress.value = cloneDeep(poi[0])
    selectAddress.value.location = location
    selectAddress.value.address = poi[0].district + poi[0].address + poi[0].name,
    console.log('handleSelect', selectAddress.value);

    updateMarker(location)
    handlerOpenInfoWindow(location)
  }
  infoWindowRef.value.reset()
}

const handleFetch = (params) => {
  console.log('params', params);
  if (!mapPlugin.placeSearch) {
    // POI搜索插件
    mapPlugin.placeSearch = new MyAMap.PlaceSearch({
      pageSize: 20, // 单页显示结果条数
      pageIndex: 1, // 页码
      citylimit: false,  //是否强制限制在设置的城市内搜索
      map: map, // 展现结果的地图实例
      autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
    })
  }

  if (!mapPlugin.autoComplete) {
    mapPlugin.autoComplete = new MyAMap.AutoComplete(autoOptions);
  }
 

  return new Promise((resolve, reject) => {
    mapPlugin.autoComplete.search(searchValue.value, function(status, result) {
      // 搜索成功时，result即是对应的匹配数据
      console.log("autoComplete", result);
      autoCompleteResult.value = result.tips || []
      const options = result?.tips?.filter(e => e.location).map(e => ({
        label: e.name,
        detail: e.district + e.address + e.name,
        value: e.id,
        key: e.id,
      }))
      resolve(options)
    })
    
  })
}

// 实例化点标记

const updateMarker = (location: Location) => {
  console.info('updateMarker-request: ', location);
  if (!location || !map) {
    return
  }
  infoWindowRef.value && infoWindowRef.value.hidden()

  if (!mapPlugin.marker) {
    mapPlugin.marker = new MyAMap.Marker({
      icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
      // position: current_position.value, // 这里我们通过上面的点击获取经纬度坐标,实时添加标记
      // 通过设置 offset 来添加偏移量
      offset: new MyAMap.Pixel(-20, -50),
    });
    mapPlugin.marker.setMap(map);
  }

   // 自定义点标记内容
  let markerContent = document.createElement("div");

  // 点标记中的图标
  let markerImg = document.createElement("img");
  markerImg.className = "markerlnglat";
  markerImg.src = "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png";
  markerContent.appendChild(markerImg);

  // 点标记中的文本
  let markerSpan = document.createElement("span");
  markerContent.appendChild(markerSpan);

  mapPlugin.marker.setContent(markerContent); //更新点标记内容
  mapPlugin.marker.setPosition([location.lng, location.lat]); //更新点标记位置

  console.log('marker updated');
  
  mapPlugin.marker.setTop(true);
  // 移动到中心
  map.setCenter(mapPlugin.marker.getPosition());
}


const handlerOpenInfoWindow = async (location: Location) => {
  console.log('infoWindow', location);
  if (selectAddress.value.address === '') {
    const addressInfo = await getAddress(location)
    console.log('address', addressInfo);
    selectAddress.value = {...selectAddress.value, ...addressInfo}
  }
 

  let infoWindow = new MyAMap.InfoWindow({
    isCustom: true,  //使用自定义窗体
    autoMove: true, // 是否自动调整窗体到视野内
    position: [location.lng, location.lat], // 基点位置
    content: document.getElementById("info-window"),
    offset: new MyAMap.Pixel(60, -200)
  });
  infoWindow.open(map, [location.lng, location.lat]);
  // 必须也设置一下, 否则居中有问题
  map.setCenter(mapPlugin.marker.getPosition());
  infoWindowRef.value && infoWindowRef.value.show()
}


const getAddress = async (location : Location) => {
  if (!mapPlugin.geocoder) {
    mapPlugin.geocoder = new MyAMap.Geocoder({
      city: "010", //城市设为北京，默认：“全国”
      radius: 1000 //范围，默认：500
    });
  }

  // @ts-ignore
  return new Promise((resolve, reject) => {
    // @ts-ignore
    mapPlugin.geocoder.getAddress([location.lng, location.lat], (status, result) => {
      console.log('result', result);
      if (result.regeocode.formattedAddress) {
        const addressComponent = result.regeocode.addressComponent
        resolve({
          address: result.regeocode.formattedAddress,
          name: addressComponent.district + addressComponent.street + addressComponent.township,
          location
        })
      } else {
        createMessage.error('地址获取失败')
        resolve({});
      }
    })
  })
}

//表单提交事件
async function handleSubmit(v) {
  try {
    setModalProps({ confirmLoading: true });
    //关闭弹窗
    closeModal();
    const addressData = unref(useAddress)
    console.log('submit data', addressData);
    if (addressData.address && addressData.address !== '' && addressData.location) {
      //刷新列表
      
      emit('success', {
        address: addressData.address,
        addressDetail: {
          location: {
            lat: addressData.location.lat,
            lng: addressData.location.lng,
          }
        }
      });
    }
    map && map.clearMap()
    map && map.destroy();
  } finally {
    setModalProps({ confirmLoading: false });
  }
}

const handleDestroy = () => {
  map && map.destroy()
  console.log('destroy map');
  return true
}

</script>

<style lang="less">
#demo-amap-container {
  padding: 0px;
  margin: 0px;
  width: 100%;
  height: 500px;
}
.demo-amap-app-container {
  margin-top: 10px;
  position: relative;
  height: calc(100% - 300px);
}

.addree-option {
  display: flex;
  justify-content: space-between;
  .label {
    margin-right: 20px;
  }

  .detail {
    color: #b2b2b2;
  }
}

.map-marker {
  position: absolute;
  top: -20px;
  right: -60px;
  color: #fff;
  padding: 4px 10px;
  box-shadow: 1px 1px 1px rgba(10, 10, 10, .2);
  white-space: nowrap;
  font-size: 12px;
  font-family: "";
  background-color: #25A5F7;
  border-radius: 3px;
}


.maps-search-select {
  position: absolute;
  left: 50%;
  top: 10px;
  border: 1px solid #ccc;
  z-index: 1000;
  transform: translate(-50%-0%);
}

</style>